package org.jhub1.system.xmpp.gateway.packet;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.jivesoftware.smack.packet.IQ;

public class IQGatewayItems extends IQ {

	private final List<Item> items = new CopyOnWriteArrayList<Item>();

	/**
	 * Adds a new item to the discovered information.
	 * 
	 * @param item
	 *            the discovered entity's item
	 */
	public void addItem(Item item) {
		synchronized (items) {
			items.add(item);
		}
	}

	/**
	 * Returns the discovered items of the queried XMPP entity.
	 * 
	 * @return an Iterator on the discovered entity's items
	 */
	public Iterator<IQGatewayItems.Item> getItems() {
		synchronized (items) {
			return Collections.unmodifiableList(items).iterator();
		}
	}

	public Iterator<IQGatewayItems.Item> getWriteItems() {
		synchronized (items) {
			return items.iterator();
		}
	}

	@Override
	public String getChildElementXML() {
		StringBuilder buf = new StringBuilder();
		buf.append("<query xmlns='jhub1:iq:gateway'>");
		synchronized (items) {
			for (Item item : items) {
				buf.append(item.toXML());
			}
		}
		buf.append("</query>");
		return buf.toString();
		// return
		// "<query xmlns='jhub1:iq:gateway'><id>34</id><values>You did it</values></query>";
	}

	public static class Item {

		private List<SubItemable> subItems = null;;
		// = new CopyOnWriteArrayList<SubItem>();
		private String name;
		private String namespace;
		private String atype;
		private String command;
		private String id;
		private String rq = null;
		private String uri;
		private String text = null;
		private String error;

		/**
		 * Create a new Item associated with a given entity.
		 * 
		 * @param entityID
		 *            the id of the entity that contains the item
		 */
		public Item(String id) {
			this.id = id;
		}

		/**
		 * Adds a new item to the discovered information.
		 * 
		 * @param item
		 *            the discovered entity's item
		 */
		public void addItem(SubItemable item) {
			synchronized (subItems) {
				subItems.add(item);
			}
		}

		/**
		 * Adds a new item to the discovered information.
		 * 
		 * @param item
		 *            the discovered entity's item
		 */
		public Iterator<SubItemable> getItems() {
			if (subItems != null) {
				return subItems.iterator();
			}
			return null;
		}

		/**
		 * Adds a new item to the discovered information.
		 * 
		 * @param item
		 *            the discovered entity's item
		 */
		public void setSubItems(List<SubItemable> subItems) {
			this.subItems = subItems;
		}

		/**
		 * Returns the entity's ID.
		 * 
		 * @return the entity's ID.
		 */
		public String getID() {
			return id;
		}

		/**
		 * Returns the entity's AccessType.
		 * 
		 * @return the entity's AccessType.
		 */
		public String getAccessType() {
			return atype;
		}

		/**
		 * Sets the entity's Text.
		 * 
		 * @param name
		 *            the entity's Text.
		 */
		public void setText(String text) {
			this.text = text;
		}

		/**
		 * Returns the entity's Text.
		 * 
		 * @return the entity's Text.
		 */
		public String getText() {
			return text;
		}

		/**
		 * Sets the entity's AccessType.
		 * 
		 * @param name
		 *            the entity's AccessType.
		 */
		public void setAccessType(String atype) {
			this.atype = atype;
		}

		/**
		 * Returns the entity's Command.
		 * 
		 * @return the entity's Command.
		 */
		public String getCommand() {
			return command;
		}

		/**
		 * Sets the entity's Command.
		 * 
		 * @param name
		 *            the entity's Command.
		 */
		public void setCommand(String command) {
			this.command = command;
		}

		/**
		 * Returns the entity's Request.
		 * 
		 * @return the entity's Request.
		 */
		public String getRequestType() {
			return rq;
		}

		/**
		 * Sets the entity's Request.
		 * 
		 * @param name
		 *            the entity's Request.
		 */
		public void setRequestType(String rq) {
			this.rq = rq;
		}

		/**
		 * Returns the entity's Uri.
		 * 
		 * @return the entity's Uri.
		 */
		public String getUri() {
			return uri;
		}

		/**
		 * Sets the entity's Uri.
		 * 
		 * @param name
		 *            the entity's Uri.
		 */
		public void setUri(String uri) {
			this.uri = uri;
		}

		/**
		 * Returns the entity's Error.
		 * 
		 * @return the entity's Error.
		 */
		public String getError() {
			return error;
		}

		/**
		 * Sets the entity's Error.
		 * 
		 * @param name
		 *            the entity's Error.
		 */
		public void setError(String error) {
			this.error = error;
		}

		/**
		 * Returns the entity's name.
		 * 
		 * @return the entity's name.
		 */
		public String getName() {
			return name;
		}

		/**
		 * Returns the entity's namespace.
		 * 
		 * @return the entity's namespace.
		 */
		public String getNamespace() {
			return namespace;
		}

		/**
		 * Sets the entity's name.
		 * 
		 * @param name
		 *            the entity's name.
		 */
		public void setName(String name) {
			this.name = name;
		}

		/**
		 * Sets the entity's namespace.
		 * 
		 * @param name
		 *            the entity's namespace.
		 */
		public void setNamespace(String namespace) {
			this.namespace = namespace;
		}

		public String toXML() {
			StringBuilder buf = new StringBuilder();
			buf.append("<jhub1data id='").append(id).append("'");
			if (atype != null) {
				buf.append(" atype='").append(atype).append("'");
			}
			if (command != null) {
				buf.append(" command='").append(command).append("'");
			}
			if (rq != null) {
				buf.append(" rq='").append(rq).append("'");
			}
			if (uri != null) {
				buf.append(" uri='").append(uri).append("'");
			}
			if (error != null) {
				buf.append(" error='").append(error).append("'");
			}
			if (text != null && text.length() > 0) {
				buf.append(">").append(text).append("</jhub1data>");
			} else if (subItems != null && subItems.size() > 0) {
				buf.append(">");
				for (SubItemable subItem : subItems) {
					buf.append(subItem.toXML());
				}
				buf.append("</jhub1data>");
			} else {
				buf.append("/>");
			}
			return buf.toString();
		}

		public static class SubItem implements SubItemable {

			private String address;
			private String value;

			public SubItem(String address, String value) {
				this.address = address;
				this.value = value;
			}

			/**
			 * Returns the entity's Address.
			 * 
			 * @return the entity's Address.
			 */
			public String getName() {
				return address;
			}

			/**
			 * Sets the entity's Address.
			 * 
			 * @param name
			 *            the entity's Address.
			 */
			public void setName(String address) {
				this.address = address;
			}

			/**
			 * Returns the entity's Value.
			 * 
			 * @return the entity's Value.
			 */
			public String getValue() {
				return value;
			}

			/**
			 * Sets the entity's Value.
			 * 
			 * @param name
			 *            the entity's Value.
			 */
			public void setValue(String value) {
				this.value = value;
			}

			public String toXML() {
				StringBuilder buf = new StringBuilder();
				buf.append("<set");
				if (address != null) {
					buf.append(" address='").append(address).append("'");
				}
				if (value != null) {
					buf.append(" value='").append(value).append("'");
				}
				buf.append("/>");
				return buf.toString();
			}
		}

		public static class SubItemParams implements SubItemable {

			private String name;
			private String value;

			public SubItemParams(String name, String value) {
				this.name = name;
				this.value = value;
			}

			/**
			 * Returns the entity's Address.
			 * 
			 * @return the entity's Address.
			 */
			public String getName() {
				return name;
			}

			/**
			 * Sets the entity's Address.
			 * 
			 * @param name
			 *            the entity's Address.
			 */
			public void setName(String name) {
				this.name = name;
			}

			/**
			 * Returns the entity's Value.
			 * 
			 * @return the entity's Value.
			 */
			public String getValue() {
				return value;
			}

			/**
			 * Sets the entity's Value.
			 * 
			 * @param name
			 *            the entity's Value.
			 */
			public void setValue(String value) {
				this.value = value;
			}

			public String toXML() {
				StringBuilder buf = new StringBuilder();
				buf.append("<param");
				if (name != null) {
					buf.append(" name='").append(name).append("'");
				}
				if (value != null) {
					buf.append(">").append(value).append("</param>");
				} else {
					buf.append("/>");
				}
				return buf.toString();
			}
		}

	}

}
